using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Chili.Opf3.Caching
{
	/// <summary>
	/// Provides a way of reading a forward-only stream of objects from a cache.
	/// </summary>
	internal sealed class CacheObjectReader<T> : ObjectReader<T>
	{
		private IList<T> _objects;
		private bool _finishedReading;
		private int _index = -1;

		/// <summary>
		/// Creates a new instance of the <see cref="CacheObjectReader{T}">CacheObjectReader Class</see>.
		/// </summary>
		/// <param name="context">The <see cref="ObjectContext">ObjectContext</see> associated with the 
		/// ObjectReader. It is required to get the <see cref="ObjectInfo">ObjectInfo</see> object
		/// of created objects.</param>
		/// <param name="objects">A list of objects that are used by the <see cref="CacheObjectReader{T}">CacheObjectReader</see>.</param>
		/// <exception cref="System.ArgumentNullException">Objects is null.</exception>
		internal CacheObjectReader(ObjectContext context, IList<T> objects)
			: base(context)
		{
			if (objects == null)
				throw new ArgumentNullException("objects");
			_objects = objects;
		}

		/// <summary>
		/// Advances the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> to one of the next records. 
		/// </summary>
		/// <param name="step">The step that is performed while reading.</param>
		/// <returns>Returns true if the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> could be
		/// advanced to the next object.</returns>
		protected override bool InternalRead(int step)
		{
			_index += step;

			if (_index > _objects.Count -1)
			{
				_finishedReading = true;
				return false;
			}

			return true;
		}

		/// <summary>
		/// Closes the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> object.
		/// </summary>
		public override void Close()
		{
			_objects = null;
		}

		/// <summary>
		/// Indicates whether the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> has been closed. 
		/// </summary>
		/// <value>Returns true if the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> is closed.</value>
		[XmlIgnore]
		public override bool IsClosed
		{
			get { return (_objects == null); }
		}

		/// <summary>
		/// Returns whether the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> contains 
		/// one or more rows. 
		/// </summary>
		/// <value>Returns true if the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> has fetched one
		/// ore more objects.</value>
		[XmlIgnore]
		public override bool HasObjects
		{
			get { return (_objects.Count > 0); }
		}

		/// <summary>
		/// Returns if the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> has finished reading. 
		/// Is true after Read returned false.
		/// </summary>
		/// <value>Returns true if the <see cref="Opf3.ObjectReader{T}">ObjectReader</see> has finished reading.</value>
		[XmlIgnore]
		public override bool FinishedReading
		{
			get { return _finishedReading; }
		}

		/// <summary>
		/// Returns the current object managed by the ObjectReader.
		/// </summary>
		/// <returns></returns>
		protected override T GetCurrentObject()
		{
			return _objects[_index];
		}
	}
}
